package com.mccken.demo.io.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @program: mccken-collect
 * @description:
 * @author: mccken
 * @create: 2022-05-02 20:25
 **/
public class SelectorDemo {

	/**
	 * 注册事件
	 */
	private Selector getSelector() throws Exception {
		// 获取selector对象
		Selector selector = Selector.open();
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		// 非阻塞
		serverSocketChannel.configureBlocking(false);
		
		// 获取socket 并绑定端口
		ServerSocket socket = serverSocketChannel.socket();
		socket.bind(new InetSocketAddress(6677));
		
		// 注册感兴趣的事件
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
		return selector;
	}
	
	private void process(SelectionKey key, Selector selector) throws IOException {
		// 新连接请求
		if (key.isAcceptable()) {
			ServerSocketChannel serverSocketChannel  = (ServerSocketChannel) key.channel();
			SocketChannel channel = serverSocketChannel.accept();
			channel.configureBlocking(false);
			channel.register(selector, SelectionKey.OP_READ);	
		}
		
		// 读数据
		else if (key.isReadable()) {
			SocketChannel channel = (SocketChannel) key.channel();
			ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
			channel.read(byteBuffer);
			System.out.println("from 客户端 " + new String(byteBuffer.array(), 0, byteBuffer.position()));
		}
	}
	
	public void listen() throws Exception {
		Selector selector = this.getSelector();
		
		while (true) {
			// 该方法会组谁，直到至少有一个事件的发生
			Set<SelectionKey> selectionKeys = selector.selectedKeys();
			Iterator<SelectionKey> iterator = selectionKeys.iterator();
			if (iterator.hasNext()) {
				SelectionKey selectionKey = iterator.next();
				process(selectionKey, selector);
				iterator.remove();
			}

			selector.select();
		}
	}
}
